package com.seari.service.Impl;/**
 * @Author zhanghongyang
 * @Date 2020/7/7 16:22
 **/

import com.seari.bean.EquipmentName;
import com.seari.mapper.EquipmentTreeMapper;
import com.seari.service.EquipmentTreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName EquipmentTreeImpl
 * @Description: 故障树节点获取
 * @Date 2020/7/7 
 * @author zhanghongyang
 **/
@Service("equipmentTreeService")
public class EquipmentTreeImpl implements EquipmentTreeService {
	public static final Object LOCK = new Object();
	private volatile List<Map<String, Object>> cachedResult = null; //结果缓存
	private List<EquipmentName> allMenus;
	private List<EquipmentName> lv1Menus;
	private List<EquipmentName> lv2Menus;
	private List<EquipmentName> lv3Menus;
	private Map<String, Integer> menuCountMap = new HashMap<>(300);
	private Map<String,EquipmentName> idAndMenuRef = new HashMap<>(300);
	
	
    @Autowired
    private EquipmentTreeMapper equipmentTreeMapper;

    @Override
    public List<EquipmentName> getEquipment() {
    	
        List<EquipmentName> lists = equipmentTreeMapper.getEquipment();

        return lists;
    }

    @Override
    public List<Map<String, Object>> getdDsposeEquipmentInfo() {
    	List<Map<String, Object>> gzSb1MapList = null;
    	//双锁判断
    	if(cachedResult == null)
    	{
    		synchronized (LOCK)
			{
				if(cachedResult == null)
				{
					List<EquipmentName> lists = equipmentTreeMapper.getEquipment();

			        List<EquipmentName> gzSb1List = new ArrayList<EquipmentName>();
			        List<EquipmentName> gzSb2List = new ArrayList<EquipmentName>();
			        List<EquipmentName> gzSb3List = new ArrayList<EquipmentName>();

			        List<EquipmentName> middList = new ArrayList<EquipmentName>();

			        for (EquipmentName equipmentName : lists) {
			            if (equipmentName.getSubId().equals("0")) {
			                gzSb1List.add(equipmentName);
			            } else {
			                middList.add(equipmentName);
			            }
			        }

			        for (EquipmentName equipmentName : gzSb1List) {
			            for (EquipmentName en : middList) {
			                if (en.getSubId().equals(equipmentName.getId())) {
			                    gzSb2List.add(en);
			                }
			            }
			        }
			        
			        for (EquipmentName equipmentName : gzSb2List) {
			            for (EquipmentName en : middList) {
			                if (en.getSubId().equals(equipmentName.getId())) {
			                    gzSb3List.add(en);
			                }
			            }
			        }
			        
			        //处理后结果集加载至成员变量
			        lv1Menus = gzSb1List; lv2Menus=gzSb2List; lv3Menus=gzSb3List;allMenus=lists;
			        generateMenuMapData();
			        gzSb1MapList = new ArrayList<Map<String, Object>>();
			        for(EquipmentName one:gzSb1List){
			            Map<String, Object> mapOne = new HashMap<String, Object>();
			            List<Map<String, Object>> gzSb2MapList = new ArrayList<Map<String, Object>>();
			            for(EquipmentName two:gzSb2List){  //1  找 2
			                if(one.getId().equals(two.getSubId())){
			                    Map<String, Object> mapTwo = new HashMap<String, Object>();
			                    List<Map<String, Object>> gzSb3MapList = new ArrayList<Map<String, Object>>();
			                    for(EquipmentName three:gzSb3List){  //2  找 3
			                        if(two.getId().equals(three.getSubId())){
			                            Map<String, Object> mapThree = new HashMap<String, Object>();
			                            mapThree.put("title",three.getSbName());
			                            mapThree.put("id",three.getId());
			                            gzSb3MapList.add(mapThree);
			                        }
			                    }
			                    mapTwo.put("title",two.getSbName());
			                    mapTwo.put("id",two.getId());
			                    mapTwo.put("children",gzSb3MapList);
			                    gzSb2MapList.add(mapTwo);
			                }
			            }
			            mapOne.put("title",one.getSbName());
			            mapOne.put("id",one.getId());
			            mapOne.put("children",gzSb2MapList);
			            gzSb1MapList.add(mapOne);
			        }
				}else {
					gzSb1MapList = cachedResult;
				}
			}
    	}else {
    		//读缓存
			gzSb1MapList = cachedResult;
		}        
        return gzSb1MapList;
    }
    
    private void generateMenuMapData()
    {
    	//将节点list映射为ID-节点键值对
    	idAndMenuRef = allMenus.stream().collect(Collectors.toMap(EquipmentName::getId, Function.identity(),(key1,key2) -> key2)); //键冲突时取后来键
    	List<EquipmentName> templist = new ArrayList<>(lv3Menus);
    	for (EquipmentName lv1 : lv1Menus)
		{
			menuCountMap.put(lv1.getId(), 0);
			lv1.setLevelOfMenu(1);
		}
    	for (EquipmentName lv2 : lv2Menus)
		{
			menuCountMap.put(lv2.getSubId(), menuCountMap.get(lv2.getSubId())+1);//一级节点子节点数加1
			Iterator<EquipmentName> iterator = templist.iterator();
			int count = 0;
			while(iterator.hasNext())
			{
				EquipmentName temp = iterator.next();
				temp.setLevelOfMenu(3);
				if(temp.getSubId().equals(lv2.getId()))
				{
					count++;
					iterator.remove();
				}
			}
			menuCountMap.put(lv2.getId(), count); //更新二级节点子节点数
			menuCountMap.put(lv2.getSubId(), menuCountMap.get(lv2.getSubId()) + count);//更新一级节点子节点数
			lv2.setLevelOfMenu(2);
		}
    	//System.out.println(menuCountMap.toString());
    }

	@Override
	public Map<String, List<String>> getMenuParams(String param)
	{
		Map<String, List<String>> resultMap = null;
		Map<String, Integer> lv1CountMap = new HashMap<>();
		Map<String, Integer> lv2CountMap = new HashMap<>();
		Set<String> lv1SubSet = new HashSet<>();
		Set<String> lv2SubSet = new HashSet<>();
		Set<String> lv1ResultSet = new HashSet<>();
		Set<String> lv2ResultSet = new HashSet<>();
		Set<String> lv3ResultSet = new HashSet<>();
		try
		{
			String[] menuIds = param.split(",");
			if(menuIds != null && menuIds.length > 0)
			{
				for (String menuId : menuIds)
				{
					if(idAndMenuRef.containsKey(menuId))
					{
						EquipmentName temp = idAndMenuRef.get(menuId);
						if(temp.getLevelOfMenu() == 1)
						{
							countToMap(lv1CountMap, menuId);
							lv1ResultSet.add(menuId);
						}else if (temp.getLevelOfMenu() == 2) {
							lv2ResultSet.add(menuId);
							countToMap(lv2CountMap, menuId);
							//获取1级菜单并计数
							countToMap(lv1CountMap, temp.getSubId());
							//临时存放对照关系
							lv1SubSet.add(menuId);
						}else if (temp.getLevelOfMenu() == 3) {
							lv3ResultSet.add(menuId);
							//获取2级菜单并计数
							countToMap(lv2CountMap, temp.getSubId());
							//临时存放对照关系
							lv2SubSet.add(menuId);
							//获取1级菜单并计数
							countToMap(lv1CountMap, idAndMenuRef.get(temp.getSubId()).getSubId());
							//临时存放对照关系
							lv1SubSet.add(menuId);
						}else {
							//do nothing
						}
					}
				}
				
				for (Entry<String, Integer> lv1 : lv1CountMap.entrySet())
				{
					if(menuCountMap.get(lv1.getKey()) == lv1.getValue())
					{
						//根据对照关系删除结果集中的数据
						for (String lv1Sub : lv1SubSet)
						{
							lv2ResultSet.remove(lv1Sub);
							lv3ResultSet.remove(lv1Sub);
						}
					}else {
						//数量结果不匹配时，删除自身
						lv1ResultSet.remove(lv1.getKey());
					}
				}
				
				for (Entry<String, Integer> lv2 : lv2CountMap.entrySet())
				{
					if(menuCountMap.get(lv2.getKey()) == lv2.getValue())
					{
						//根据对照关系删除结果集中的数据
						for (String lv2Sub : lv2SubSet)
						{
							lv3ResultSet.remove(lv2Sub);
						}
					}else {
						//数量结果不匹配时，删除自身
						lv2ResultSet.remove(lv2.getKey());
					}
				}
				resultMap = new HashMap<>();
				resultMap.put("lv1", lv1ResultSet.size() > 0 ? new ArrayList<>(lv1ResultSet) : null);
				resultMap.put("lv2", lv2ResultSet.size() > 0 ? new ArrayList<>(lv2ResultSet) : null);
				resultMap.put("lv3", lv3ResultSet.size() > 0 ? new ArrayList<>(lv3ResultSet) : null);
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return resultMap;
	}
	
	private void countToMap(Map<String, Integer> map,String id)
	{
		if(map.containsKey(id))
		{
			map.put(id, map.get(id)+1);
		}else {
			map.put(id, 0);
		}
	}
}
